﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using HSFB.Lib;
using System.Diagnostics;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace HSFB.Test
{
    /// <summary>
    /// Unit testig of FizzBuzz exercise
    /// </summary>
    [TestClass]
    public class FBLib
    {

        /// <summary>
        /// Test for increasing range
        /// default labels
        /// output to console
        /// </summary>
        [TestMethod]
        public void Test_1_100()
        {
            Lib.FB.Run(1, 100);
        }

        /// <summary>
        /// Test for decreasing range
        /// default labels
        /// output to console
        /// </summary>
        [TestMethod]
        public void Test_100_0()
        {
            Lib.FB.Run(100, 0);
        }

        /// <summary>
        /// Test for negative range to positive
        /// default labels
        /// output to console
        /// </summary>
        [TestMethod]
        public void Test_Neg100_100()
        {
            Lib.FB.Run(-100, 100);
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output Trace log file
        /// </summary>
        [TestMethod]
        public void Test_Trace_File()
        {
            var trace = Trace.Listeners["LogFile"];

            Lib.FB.Run(
                trace,
                1, 100, "Works?", "For real!");

            trace.Flush();
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output Trace Console
        /// </summary>
        [TestMethod]
        public void Test_Trace_Console()
        {
            var trace = Trace.Listeners["Console"];

            Lib.FB.Run(
                trace,
                1, 100, "Works?", "For real!");

            trace.Flush();
        }

        /// <summary>
        /// Test for null trace instance
        /// different labels
        /// output defaults to console
        /// </summary>
        [TestMethod,
        ExpectedException(typeof(System.NullReferenceException))]
        public void Test_Trace_Null()
        {
            TraceListener trace = null;

            Lib.FB.Run(
                trace,
                1, 100, "Works?", "For real!");

            trace.Flush();
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to ICollection
        /// </summary>
        [TestMethod]
        public void Test_Collection()
        {
            var values = new List<string>();

            Lib.FB.Run(values,
                1, 100, "Works?", "For real!");

            values.ForEach(value =>
                Console.WriteLine(value));

            Assert.IsTrue(values.Count > 0);
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to Default console
        /// </summary>
        [TestMethod]
        public void Test_Collection_Null()
        {
            List<string> values = null;

            Lib.FB.Run(values,
                1, 100, "Works?", "For real!");

            Assert.IsNull(values);
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to String Writer
        /// </summary>
        [TestMethod]
        public void Test_TextWriter()
        {
            var sb = new StringBuilder();
            var writer = new StringWriter(sb);

            Lib.FB.Run(writer,
                1, 100, "Works?", "For real!");

            var values = sb.ToString();
            Console.Write(values);

            Assert.IsTrue(!string.IsNullOrEmpty(values));
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to Default console
        /// </summary>
        [TestMethod]
        public void Test_TextWriter_Null()
        {
            StringWriter writer = null;

            Lib.FB.Run(writer,
                1, 100, "Works?", "For real!");

        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to String Stream
        /// </summary>
        [TestMethod]
        public void Test_Stream()
        {
            using (var stream = new MemoryStream())
            {
                Lib.FB.Run(stream, Encoding.Unicode,
                    1, 100, "Works?", "For real!");

                stream.Position = 0;

                using (var reader = new StreamReader(stream, Encoding.Unicode))
                {
                    var values = reader.ReadToEnd();
                    Console.Write(values);
                }
            }
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to Default console
        /// </summary>
        [TestMethod]
        public void Test_Stream_Null()
        {
            using (MemoryStream stream = null)
            {
                Lib.FB.Run(stream, Encoding.Unicode,
                    1, 100, "Works?", "For real!");

                Assert.IsNull(stream);
            }
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to FBWriter 
        /// </summary>
        [TestMethod]
        public void Test_FBWriter()
        {

            var writer = new FBWriter();

            Lib.FB.Run(writer,
                1, 100, "Works?", "For real!");

            var values = writer.ReadAll();

            Console.Write(values);
            Assert.IsTrue(!string.IsNullOrEmpty(values));
        }

        /// <summary>
        /// Test for different output
        /// different labels
        /// output to Default console 
        /// </summary>
        [TestMethod]
        public void Test_FBWriter_Null()
        {

            FBWriter writer = null;

            Lib.FB.Run(writer,
                1, 100, "Works?", "For real!");

            Assert.IsNull(writer);
        }
    }
}
